import { App, Modal, Segmented } from 'antd';
import { customAlphabet } from 'nanoid';
import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next';

import { VariableItemType } from '@/types/app/type';
import {
  FlowNodeInputTypeEnum,
  WorkflowIOValueTypeEnum,
  VariableInputEnum,
} from '@/types/workflow/constant';
import { UserInputFormItemType } from '@/types/workflow/template/system/interactive/type';

import InputTypeConfig from '../NodePluginIO/InputTypeConfig';

const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 6);

// 映射函数：将 FlowNodeInputTypeEnum 转换为 VariableInputEnum
const mapToVariableInputEnum = (type: FlowNodeInputTypeEnum): VariableInputEnum => {
  const mapping: Record<FlowNodeInputTypeEnum, VariableInputEnum> = {
    [FlowNodeInputTypeEnum.input]: VariableInputEnum.input,
    [FlowNodeInputTypeEnum.textarea]: VariableInputEnum.textarea,
    [FlowNodeInputTypeEnum.numberInput]: VariableInputEnum.numberInput,
    [FlowNodeInputTypeEnum.select]: VariableInputEnum.select,
    [FlowNodeInputTypeEnum.cascader]: VariableInputEnum.cascader,
    [FlowNodeInputTypeEnum.switch]: VariableInputEnum.switch,
    [FlowNodeInputTypeEnum.time]: VariableInputEnum.time,
    [FlowNodeInputTypeEnum.reference]: VariableInputEnum.input,
    [FlowNodeInputTypeEnum.JSONEditor]: VariableInputEnum.textarea,
    [FlowNodeInputTypeEnum.addInputParam]: VariableInputEnum.input,
    [FlowNodeInputTypeEnum.selectApp]: VariableInputEnum.select,
    [FlowNodeInputTypeEnum.customVariable]: VariableInputEnum.custom,
    [FlowNodeInputTypeEnum.selectLLMModel]: VariableInputEnum.select,
    [FlowNodeInputTypeEnum.settingLLMModel]: VariableInputEnum.custom,
    [FlowNodeInputTypeEnum.selectDataset]: VariableInputEnum.select,
    [FlowNodeInputTypeEnum.selectDatasetParamsModal]: VariableInputEnum.custom,
    [FlowNodeInputTypeEnum.settingDatasetQuotePrompt]: VariableInputEnum.textarea,
    [FlowNodeInputTypeEnum.hidden]: VariableInputEnum.input,
    [FlowNodeInputTypeEnum.custom]: VariableInputEnum.custom,
  };
  return mapping[type] || VariableInputEnum.input;
};

// 映射函数：将 VariableInputEnum 转换为 FlowNodeInputTypeEnum
const mapToFlowNodeInputTypeEnum = (type: VariableInputEnum): FlowNodeInputTypeEnum => {
  const mapping: Record<VariableInputEnum, FlowNodeInputTypeEnum> = {
    [VariableInputEnum.input]: FlowNodeInputTypeEnum.input,
    [VariableInputEnum.textarea]: FlowNodeInputTypeEnum.textarea,
    [VariableInputEnum.numberInput]: FlowNodeInputTypeEnum.numberInput,
    [VariableInputEnum.select]: FlowNodeInputTypeEnum.select,
    [VariableInputEnum.cascader]: FlowNodeInputTypeEnum.cascader,
    [VariableInputEnum.switch]: FlowNodeInputTypeEnum.switch,
    [VariableInputEnum.time]: FlowNodeInputTypeEnum.time,
    [VariableInputEnum.custom]: FlowNodeInputTypeEnum.custom,
  };
  return mapping[type] || FlowNodeInputTypeEnum.input;
};

// 适配器函数：将 UserInputFormItemType 转换为 FlowNodeInputItemType
const adaptToFlowNodeInput = (
  data: UserInputFormItemType,
): VariableItemType & { list?: { id: string; value: string; label: string }[] } => ({
  id: nanoid(),
  key: data.key,
  label: data.label,
  type: mapToVariableInputEnum(data.type),
  required: data.required,
  description: data.description || '',
  valueType: data.valueType,
  defaultValue: data.defaultValue,
  isArray: data.isArray,
  pattern: data.pattern,
  maxLength: data.maxLength,
  max: data.max,
  min: data.min,
  enums: data.list?.map((item) => ({ value: item.value, label: item.label })),
  list: data.list?.map((item) => ({
    id: nanoid(),
    value: item.value,
    label: item.label,
    children: item.children,
  })),
});

// 适配器函数：将 FlowNodeInputItemType 转换回 UserInputFormItemType
const adaptFromFlowNodeInput = (
  data: VariableItemType & {
    list?: {
      children: any;
      id: string;
      value: string;
      label: string;
    }[];
  },
): UserInputFormItemType => ({
  type: mapToFlowNodeInputTypeEnum(data.type),
  key: data.key,
  label: data.label,
  value: data.defaultValue,
  valueType: data.valueType || WorkflowIOValueTypeEnum.string,
  description: data.description,
  defaultValue: data.defaultValue,
  required: data.required,
  maxLength: data.maxLength,
  isArray: data.isArray,
  pattern: data.pattern,
  max: data.max,
  min: data.min,
  list: data.list?.map((item) => ({
    value: item.value,
    label: item.label,
    children: item.children,
  })) || [{ label: '', value: '', children: [] }],
});

export const defaultFormInput: UserInputFormItemType = {
  type: FlowNodeInputTypeEnum.input,
  key: '',
  label: '',
  description: '',
  value: '',
  maxLength: undefined,
  defaultValue: '',
  valueType: WorkflowIOValueTypeEnum.string,
  required: false,
  list: [{ label: '', value: '', children: [] }],
  isArray: false,
  pattern: '',
};

// Modal for add or edit user input form items
const InputFormEditModal = ({
  defaultValue,
  onClose,
  onSubmit,
  keys,
}: {
  defaultValue: UserInputFormItemType;
  onClose: () => void;
  onSubmit: (data: UserInputFormItemType) => void;
  keys: string[];
}) => {
  const { message } = App.useApp();
  const isEdit = !!defaultValue.key;
  const { t } = useTranslation();

  // 使用适配后的类型进行状态管理
  const [flowNodeData, setFlowNodeData] = React.useState(() => adaptToFlowNodeInput(defaultValue));
  const data = adaptFromFlowNodeInput(flowNodeData);

  const inputType = data.type || FlowNodeInputTypeEnum.input;

  const inputTypeList = [
    {
      label: t('core.workflow.inputType.textInput'),
      value: FlowNodeInputTypeEnum.input,
      defaultValueType: WorkflowIOValueTypeEnum.string,
    },
    {
      label: t('core.workflow.inputType.number input'),
      value: FlowNodeInputTypeEnum.numberInput,
      defaultValueType: WorkflowIOValueTypeEnum.number,
    },
    {
      label: t('core.workflow.inputType.select'),
      value: FlowNodeInputTypeEnum.select,
      defaultValueType: WorkflowIOValueTypeEnum.string,
    },
    {
      label: t('core.workflow.inputType.tree'),
      value: FlowNodeInputTypeEnum.cascader,
      defaultValueType: WorkflowIOValueTypeEnum.arrayString,
    },
    {
      label: t('core.workflow.inputType.switch'),
      value: FlowNodeInputTypeEnum.switch,
      defaultValueType: WorkflowIOValueTypeEnum.boolean,
    },
    {
      label: t('core.workflow.inputType.timeSelect'),
      value: FlowNodeInputTypeEnum.time,
      defaultValueType: WorkflowIOValueTypeEnum.time,
    },
  ];

  const defaultValueType = inputTypeList
    .flat()
    .find((item) => item.value === inputType)?.defaultValueType;

  const onSubmitSuccess = (flowData: VariableItemType, action: 'confirm' | 'continue') => {
    const adaptedData = adaptFromFlowNodeInput(flowData as any);
    const isChangeKey = defaultValue.key !== adaptedData.key;
    adaptedData.key = adaptedData.key.trim();
    adaptedData.label = adaptedData.label.trim();
    if (adaptedData.key === '') {
      message.warning(t('field_key_cannot_be_empty'));
      return;
    }
    if (adaptedData.label === '') {
      message.warning(t('field_label_cannot_be_empty'));
      return;
    }

    if (keys.includes(adaptedData.key)) {
      if (!isEdit || isChangeKey) {
        message.warning(t('field_name_already_exists'));
        return;
      }
    }

    adaptedData.valueType = adaptedData.valueType || defaultValueType;

    if (action === 'confirm') {
      onSubmit(adaptedData);
      onClose();
    } else if (action === 'continue') {
      onSubmit(adaptedData);
      message.success(t('common.Add Success'));
      setFlowNodeData(adaptToFlowNodeInput(defaultFormInput));
    }
  };

  const onSubmitError = useCallback(
    (e: Record<string, { message?: string }>) => {
      const errorItem = Object.values(e).find((item) => !!item.message);
      if (errorItem && errorItem.message) {
        message.warning(errorItem.message);
      }
    },
    [message],
  );

  return (
    <Modal
      open
      onCancel={onClose}
      title={isEdit ? t('edit_input') : t('add_new_input')}
      width="600"
      style={{ maxWidth: 800, minWidth: 800 }}
      footer={null}
      centered
    >
      <div className="flex flex-col gap-2">
        <Segmented
          block
          onChange={(value) => {
            setFlowNodeData((prev) => {
              if (value === FlowNodeInputTypeEnum.time) {
                if (
                  prev.valueType !== undefined &&
                  [
                    WorkflowIOValueTypeEnum.time,
                    WorkflowIOValueTypeEnum.date,
                    WorkflowIOValueTypeEnum.datetime,
                  ].includes(prev.valueType)
                ) {
                  return {
                    ...prev,
                    type: mapToVariableInputEnum(value),
                    valueType: prev.valueType,
                  };
                }
                return {
                  ...prev,
                  type: mapToVariableInputEnum(value),
                  valueType: WorkflowIOValueTypeEnum.time,
                };
              }
              return {
                ...prev,
                type: mapToVariableInputEnum(value),
                valueType: defaultValueType as WorkflowIOValueTypeEnum,
              };
            });
          }}
          className="custom-segmented h-11"
          options={inputTypeList}
          value={inputType}
        />

        <InputTypeConfig
          data={flowNodeData}
          setData={setFlowNodeData}
          type="formInput"
          isEdit={isEdit}
          inputType={inputType}
          onClose={onClose}
          onSubmitSuccess={onSubmitSuccess}
          onSubmitError={onSubmitError}
        />
      </div>
    </Modal>
  );
};

export default React.memo(InputFormEditModal);
